/*
 * bencoder.c
 *
 *  Created on: 04/07/2009
 *      Author: andre
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

#include "aatracker.h"
#include "trackerlogger.h"
#include "trackerutils.h"
#include "bencoder.h"



int bencodeAnnounceResponse(AnnounceResults *ar, BencodedResponse *br){

    //empty peerlists in request with peers = error
    if (ar->numberOfPeers != 0 && ar->peers[0] =='\0'){
        logError("bencodeAnnounceResponse", "peerlist to bencode is null", __FILE__, __LINE__, 0);
        return PEER_LIST_IS_NULL;
    }

    if (br == NULL){
        logError("bencodeAnnounceResponse", "buffer to write the bencoded string is null", __FILE__, __LINE__, 0);
        return BENCODED_RESPONSE_CONTAINER_IS_NULL;
    }

    if (ar->numberOfPeers > MAX_PEERS_IN_RESPONSE){ ar->numberOfPeers = MAX_PEERS_IN_RESPONSE;}

    int numberOfBytesInPeerList =(ar->numberOfPeers)*6;


    /*o jeito mais rapido de fazer o bencode do response eh jogar tudo em um sprintf e usar a formatacao dele pra transformar int em string   */
    int numPrintedChars = sprintf (br->str, "d8:intervali%de8:completei%de10:incompletei%de5:peers%d:", ANNOUNCE_INTERVAL, ar->complete, ar->incomplete, numberOfBytesInPeerList);

    //55 eh o numero minimo de chars da string depois do sprintf. se tiver menos que isso deu pau no sprintf
    if (numPrintedChars < MINIMAL_RESPONSE_LENGTH ){
        logError("bencodeAnnounceResponse", "error bencoding response: minimum number of chars was not written to response string", __FILE__, __LINE__, 0);
        return ERROR_CREATING_BENCODED_RESPONSE;
    }

    if (ar->peers != NULL){
        // a peerlist nao pode ser posta na string usando sprintf pq pode ter valores como 0, que dao pau no sprintf
        memcpy(&(br->str[numPrintedChars]), ar->peers, numberOfBytesInPeerList);
    }

    //pondo um 'e', que indica o final do dicionario de peers
    br->str[numPrintedChars+numberOfBytesInPeerList] = 'e';
    //pondo um 'e', que indica o final do dicionario de response
    br->str[numPrintedChars+numberOfBytesInPeerList+1] = 'e';

    //setando o tamanho final da string
    br->bencodedResponseLength =numPrintedChars+numberOfBytesInPeerList+2;

    return OK;
}

int bencodeErrorMessage(char *errorMessage, BencodedResponse *br){

    if (errorMessage ==NULL || br == NULL){
            logError("bencodeErrorMessage", "error message or buffer to write the response is null", __FILE__, __LINE__, 0);
            return PARAMETER_IS_NULL;
    }

    //reimplementation of strnlen for nongnu systems. see man sstrnlen for details
    int errorMsgLength = strnlen2(errorMessage, 200);

    /*o jeito mais rapido de fazer o bencode de uma mensagem de erro eh jogar tudo em um sprintf*/
    int numPrintedChars = sprintf (br->str, "d14:failure reason%d:%see",errorMsgLength, errorMessage);

    if (numPrintedChars < MINIMAL_ERROR_MESSAGE_LENGTH ){
        logError("bencodeErrorMessage", "error bencoding error message: minimum number of chars was not written to response string", __FILE__, __LINE__, 0);
        return ERROR_BENCODING_ERROR_MESSAGE;
    }

    //setando o tamanho final da string
    br->bencodedResponseLength =numPrintedChars;

    return OK;
}

